﻿namespace FR.SAFTAnalyser.ViewModels.Workspace
{
    using AvalonDock.Layout.Serialization;
    using Cinch;
    using FR.SAFTAnalyser.Model;
    using FR.SAFTAnalyser.Services;
    using FR.SAFTAnalyser.ViewModels.Base;
    using FR.SAFTAnalyser.ViewModels.Pane;
    using FR.SAFTAnalyser.ViewModels.Tools;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Input;
    using System.Windows.Threading;

    partial class Workspace : Cinch.ViewModelBase
    {
        #region fields
        public const string LayoutFileName = "SAFTAnalyserLayout.config";

        //private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private bool? mDialogCloseResult;
        private bool mShutDownInProgress;
        private bool mShutDownInProgress_Cancel;

        private ObservableCollection<DocumentPartViewModel> documentParts = null;
        ObservableCollection<ToolViewModel> tools;

        private DocumentPartViewModel activeDocument = null;
        #endregion fields

        #region Singleton
        private static volatile Workspace instance;
        private static object syncRoot = new Object();

        #region constructor
        /// <summary>
        /// Constructor
        /// </summary>
        private Workspace()
        {
            this.mDialogCloseResult = null;
            this.mShutDownInProgress = mShutDownInProgress_Cancel = false;
            Mediator.Instance.Register(this);

            this.AboutCommand = new SimpleCommand<object, object>(About);
            this.SettingsCommand = new SimpleCommand<object, object>(Settings);
            this.DoOpenMainWebSiteCommand = new SimpleCommand<object, object>(CanOpenMainWebSite, OpenMainWebSite);

            //titulo por defeito
            this.Title = "";
        }
        #endregion constructor

        public static Workspace Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new Workspace();
                    }
                }

                return instance;
            }
        }
        #endregion Sigleton

        #region Properties

        #region ActiveDocument
        public DocumentPartViewModel ActiveDocument
        {
            get { return activeDocument; }
            set
            {
                if (activeDocument != value)
                {
                    activeDocument = value;

                    NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.ActiveDocument));
                }
            }
        }
        #endregion

        #region Individual document parts
        SaftViewModel saft;
        public SaftViewModel Saft
        {
            get
            {
                if (saft == null) saft = new SaftViewModel();
                return saft;
            }
            set
            {
                saft = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Saft));
            }
        }
        HeaderViewModel header;
        public HeaderViewModel Header
        {
            get
            {
                if (header == null) header = new HeaderViewModel();
                return header;
            }
            set
            {
                header = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Header));
            }
        }
        InvoicesViewModel invoices;
        public InvoicesViewModel Invoices
        {
            get
            {
                if (invoices == null) invoices = new InvoicesViewModel();
                return invoices;
            }
            set
            {
                invoices = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Invoices));
            }
        }
        InvoiceViewModel invoiceDetails;
        public InvoiceViewModel InvoiceDetails
        {
            get { return invoiceDetails; }
            set
            {
                invoiceDetails = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.InvoiceDetails));
            }
        }
        InvoicesSummaryViewModel invoicesSummary;
        public InvoicesSummaryViewModel InvoicesSummary
        {
            get
            {
                if (invoicesSummary == null) invoicesSummary = new InvoicesSummaryViewModel();
                return invoicesSummary;
            }
            set
            {
                invoicesSummary = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.InvoicesSummary));
            }
        }
        PaymentsViewModel payments;
        public PaymentsViewModel Payments
        {
            get
            {
                if (payments == null) payments = new PaymentsViewModel();
                return payments;
            }
            set
            {
                payments = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Payments));
            }
        }
        MovementOfGoodsViewModel movementOfGoods;
        public MovementOfGoodsViewModel MovementOfGoods
        {
            get
            {
                if (movementOfGoods == null) movementOfGoods = new MovementOfGoodsViewModel();
                return movementOfGoods;
            }
            set
            {
                movementOfGoods = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.MovementOfGoods));
            }
        }
        WorkingDocumentsViewModel workingDocuments;
        public WorkingDocumentsViewModel WorkingDocuments
        {
            get
            {
                if (workingDocuments == null) workingDocuments = new WorkingDocumentsViewModel();
                return workingDocuments;
            }
            set
            {
                workingDocuments = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.WorkingDocuments));
            }
        }
        GeneralLedgerEntriesViewModel generalLedgerEntries;
        public GeneralLedgerEntriesViewModel GeneralLedgerEntries
        {
            get
            {
                if (generalLedgerEntries == null) generalLedgerEntries = new GeneralLedgerEntriesViewModel();
                return generalLedgerEntries;
            }
            set
            {
                generalLedgerEntries = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.GeneralLedgerEntries));
            }
        }
        GeneralLedgerViewModel generalLedger;
        public GeneralLedgerViewModel GeneralLedger
        {
            get
            {
                if (generalLedger == null) generalLedger = new GeneralLedgerViewModel();
                return generalLedger;
            }
            set
            {
                generalLedger = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.GeneralLedger));
            }
        }
        CustomersViewModel customers;
        public CustomersViewModel Customers
        {
            get
            {
                if (customers == null) customers = new CustomersViewModel();
                return customers;
            }
            set
            {
                customers = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Customers));
            }
        }
        SupplierViewModel supplier;
        public SupplierViewModel Supplier
        {
            get
            {
                if (supplier == null) supplier = new SupplierViewModel();
                return supplier;
            }
            set
            {
                supplier = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Supplier));
            }
        }
        ProdutsViewModel products;
        public ProdutsViewModel Products
        {
            get
            {
                if (products == null) products = new ProdutsViewModel();
                return products;
            }
            set
            {
                products = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Products));
            }
        }
        TaxViewModel tax;
        public TaxViewModel Tax
        {
            get
            {
                if (tax == null) tax = new TaxViewModel();
                return tax;
            }
            set
            {
                tax = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.Tax));
            }
        }

        StockHeaderViewModel stockHeader;
        public StockHeaderViewModel StockHeader
        {
            get
            {
                if (stockHeader == null) stockHeader = new StockHeaderViewModel();
                return stockHeader;
            }
            set
            {
                stockHeader = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.StockHeader));
            }
        }

        StocksProductsViewModel stockProducts;
        public StocksProductsViewModel StockProducts
        {
            get
            {
                if (stockProducts == null) stockProducts = new StocksProductsViewModel();
                return stockProducts;
            }
            set
            {
                stockProducts = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.StockProducts));
            }
        }
        #endregion

        #region tools
        ConvertPemKeyViewModel convertPemKey;
        public ConvertPemKeyViewModel ConvertPemKey
        {
            get
            {
                if (convertPemKey == null) convertPemKey = new ConvertPemKeyViewModel();
                return convertPemKey;
            }
            set
            {
                convertPemKey = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.ConvertPemKey));
            }
        }
        ErrorMessagesViewModel errorMessages;
        public ErrorMessagesViewModel ErrorMessages
        {
            get
            {
                if (errorMessages == null) errorMessages = new ErrorMessagesViewModel();
                return errorMessages;
            }
            set
            {
                errorMessages = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.ErrorMessages));
            }
        }
        DocumentPartsViewModel saftPartsViewModel;
        public DocumentPartsViewModel SaftParts
        {
            get
            {
                if (saftPartsViewModel == null) saftPartsViewModel = new DocumentPartsViewModel();
                return saftPartsViewModel;
            }
            set
            {
                saftPartsViewModel = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(c => c.SaftParts));
            }
        }
        private SaveToBDViewModel saveBD;
        public SaveToBDViewModel SaveBD
        {
            get
            {
                if (saveBD == null) saveBD = new SaveToBDViewModel();
                return saveBD;
            }
            set { saveBD = value; }
        }
        private CreateHashFromUserInputViewModel createHashFromUserInput;
        public CreateHashFromUserInputViewModel CreateHashFromUserInput
        {
            get
            {
                if (createHashFromUserInput == null) createHashFromUserInput = new CreateHashFromUserInputViewModel();
                return createHashFromUserInput;
            }
            set { createHashFromUserInput = value; }
        }

        #endregion

        public ObservableCollection<DocumentPartViewModel> DocumentParts
        {
            get
            {
                if (documentParts == null)
                {
                    documentParts = new ObservableCollection<DocumentPartViewModel>();

                    documentParts.Add(this.Saft);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Header).IsOpenByDefault)
                        documentParts.Add(this.Header);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Payments).IsOpenByDefault)
                        documentParts.Add(this.Payments);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.MovementOfGoods).IsOpenByDefault)
                        documentParts.Add(this.MovementOfGoods);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.WorkingDocuments).IsOpenByDefault)
                        documentParts.Add(this.WorkingDocuments);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.GeneralLeaderEntries).IsOpenByDefault)
                        documentParts.Add(this.GeneralLedgerEntries);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.GeneralLeader).IsOpenByDefault)
                        documentParts.Add(this.GeneralLedger);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Customers).IsOpenByDefault)
                        documentParts.Add(this.Customers);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Suppliers).IsOpenByDefault)
                        documentParts.Add(this.Supplier);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Products).IsOpenByDefault)
                        documentParts.Add(this.Products);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Taxes).IsOpenByDefault)
                        documentParts.Add(this.Tax);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.Invoices).IsOpenByDefault)
                    {
                        documentParts.Add(this.Invoices);
                        documentParts.Add(this.InvoicesSummary);
                    }
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.StockHeader).IsOpenByDefault)
                        documentParts.Add(this.StockHeader);
                    if (Config.OpenedTables.First(t => t.Table == DocumentTables.StockProducts).IsOpenByDefault)
                        documentParts.Add(this.StockProducts);
                }

                return documentParts;
            }
            set
            {
                documentParts = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.DocumentParts));
            }
        }

        public ObservableCollection<ToolViewModel> Tools
        {
            get
            {
                if (tools == null)
                {
                    tools = new ObservableCollection<ToolViewModel>();
                    tools.Add(this.ErrorMessages);
                    tools.Add(this.SaftParts);
                    tools.Add(this.ConvertPemKey);
                    tools.Add(this.SaveBD);
                    tools.Add(this.CreateHashFromUserInput);
                }

                return tools;
            }
        }

        string mensagemStatus;
        public string MensagemStatus
        {
            get { return mensagemStatus; }
            set
            {
                mensagemStatus = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.MensagemStatus));

                this.ErrorMessages.IsSelected = true;
                this.ErrorMessages.IsVisible = true;
                this.ErrorMessages.IsActive = true;
            }
        }

        string title;
        public string Title
        {
            get { return title; }
            set
            {
                title = string.Format("Visual SAF-T PT - {0}", value);
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.Title));
            }
        }

        string versaoSAFT;
        public string VersaoSAFT
        {
            get { return versaoSAFT; }
            set
            {
                versaoSAFT = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.VersaoSAFT));
            }
        }

        string ficheiroSAFT;
        public string FicheiroSAFT
        {
            get { return string.IsNullOrEmpty(ficheiroSAFT) ? "Nenhum ficheiro aberto" : ficheiroSAFT; }
            set
            {
                ficheiroSAFT = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.FicheiroSAFT));
            }
        }

        string versaoSTOCK;
        public string VersaoSTOCK
        {
            get { return versaoSTOCK; }
            set
            {
                versaoSTOCK = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.VersaoSTOCK));
            }
        }
        string ficheiroSTOCK;
        public string FicheiroSTOCK
        {
            get { return string.IsNullOrEmpty(ficheiroSTOCK) ? "Nenhum ficheiro aberto" : ficheiroSTOCK; }
            set
            {
                ficheiroSTOCK = value;
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.FicheiroSTOCK));
            }
        }

        public int ThemeID
        {
            get { return this.Config.ThemeID; }
            set { this.Config.ThemeID = value; }
        }

        internal bool ShutDownInProgress_Cancel
        {
            get { return this.mShutDownInProgress_Cancel; }
            set
            {
                if (this.mShutDownInProgress_Cancel != value)
                {
                    this.mShutDownInProgress_Cancel = value;
                    NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.ShutDownInProgress_Cancel));
                }
            }
        }

        public string MainWebSite
        {
            get { return HyperlinkService.MainWebSite; }
            set
            {
                NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.MainWebSite));
            }
        }

        #region ApplicationName
        internal string ApplicationTitle
        {
            get { return Assembly.GetEntryAssembly().GetName().Name; }
        }
        #endregion ApplicationName

        #endregion Properties

        #region Commands
        public SimpleCommand<object, object> SettingsCommand { get; private set; }

        internal void Settings(Object args)
        {
            ViewModels.SettingsViewModel vm = new SettingsViewModel();
            Services.ServiceResolver.Instance.UIVisualizerService.ShowDialog("SettingsView", vm);
        }

        public SimpleCommand<object, object> AboutCommand { get; private set; }

        internal void About(Object args)
        {
            ViewModels.AboutViewModel vm = new AboutViewModel();
            Services.ServiceResolver.Instance.UIVisualizerService.ShowDialog("AboutView", vm);
        }

        public SimpleCommand<object, object> DoOpenMainWebSiteCommand { get; private set; }
        private void OpenMainWebSite(object args)
        {
            HyperlinkService.OpenLink(this.MainWebSite);
        }
        private bool CanOpenMainWebSite(object args)
        {
            return true;
        }
        #endregion Commands

        #region Message mediator
        [MediatorMessageSink(MessageType.SAFT_HASH_RESULTS)]
        private void LoadHashValidationResults(Error[] error)
        {
            this.MensagemStatus = UpdateStatusMessage();
        }
        [MediatorMessageSink(MessageType.SAFT_SCHEMA_RESULTS)]
        private void LoadSchemaValidationResults(Error[] error)
        {
            this.MensagemStatus = UpdateStatusMessage();
        }
        [MediatorMessageSink(MessageType.ERROR_FOUND)]
        private void LoadError(Error[] error)
        {
            this.MensagemStatus = UpdateStatusMessage();
        }
        [MediatorMessageSink(MessageType.EXCEPTION_FOUND)]
        private void LoadException(string exception)
        {
            this.MensagemStatus = exception;
        }

        [MediatorMessageSink(MessageType.SAFT_FILE_CHANGED)]
        private void SaftFileChanged(string filename)
        {
            this.FicheiroSAFT = filename;
        }

        [MediatorMessageSink(MessageType.OPEN_STOCK_FILE)]
        private void StockFileChanged(string filename)
        {
            this.FicheiroSTOCK = filename;
        }

        [MediatorMessageSink(MessageType.FOCUS_INVOICES)]
        private void FocusInvoice(string s)
        {
            this.SetActiveDocument(this.Invoices);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_INVOICE, s);
        }
        [MediatorMessageSink(MessageType.FOCUS_INVOICES_LINE)]
        private void FocusInvoiceLine(string s)
        {
            this.SetActiveDocument(this.Invoices);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_INVOICE_LINE, s);
        }
        [MediatorMessageSink(MessageType.FOCUS_HEADER)]
        private void FocusHeader(string s)
        {
            this.SetActiveDocument(this.Header);
        }
        [MediatorMessageSink(MessageType.FOCUS_CUSTOMERS)]
        private void FocusCustomer(string s)
        {
            this.SetActiveDocument(this.Customers);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_CUSTOMER, s);
        }
        [MediatorMessageSink(MessageType.FOCUS_PRODUCTS)]
        private void FocusProduct(string s)
        {
            this.SetActiveDocument(this.Products);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_PRODUCT, s);
        }
        [MediatorMessageSink(MessageType.FOCUS_SUPPLIERS)]
        private void FocusSupplier(string s)
        {
            this.SetActiveDocument(this.Supplier);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_SUPPLIER, s);
        }
        [MediatorMessageSink(MessageType.FOCUS_TAXS)]
        private void FocusTax(string s)
        {
            this.SetActiveDocument(this.Tax);

            Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.FOCUS_TAX, s);
        }
        #endregion Message mediator

        #region methods

        internal void ShowCreateHashTool(SourceDocumentsSalesInvoicesInvoice invoice, string hashDocumentoAnterior)
        {
            this.CreateHashFromUserInput.InitFromInvoice(invoice, hashDocumentoAnterior);

            this.CreateHashFromUserInput.IsSelected = true;
            this.CreateHashFromUserInput.IsVisible = true;
            this.CreateHashFromUserInput.IsActive = true;
        }

        internal void ShowCreateHashTool(SourceDocumentsMovementOfGoodsStockMovement movement, string hashDocumentoAnterior)
        {
            this.CreateHashFromUserInput.InitFromMovement(movement, hashDocumentoAnterior);

            this.CreateHashFromUserInput.IsSelected = true;
            this.CreateHashFromUserInput.IsVisible = true;
            this.CreateHashFromUserInput.IsActive = true;
        }

        internal void ShowCreateHashTool(SourceDocumentsWorkingDocumentsWorkDocument doc, string hashDocumentoAnterior)
        {
            this.CreateHashFromUserInput.InitFromMovement(doc, hashDocumentoAnterior);

            this.CreateHashFromUserInput.IsSelected = true;
            this.CreateHashFromUserInput.IsVisible = true;
            this.CreateHashFromUserInput.IsActive = true;
        }
        internal void OpenSaftFile(string filename)
        {
            //on file open request all document parts to reset there values
            foreach (DocumentPartViewModel vm in this.DocumentParts)
            {
                vm.ResetSaftFile();
            }

            if (File.Exists(filename))
            {
                SAFT.SaftAnalyser.Instance.SaftFileName = filename;
                SAFT.SaftAnalyser.Instance.LoadFileAsync();
                Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.SAFT_FILE_CHANGED, filename);

                if (this.Config.RememberLastOpenFiles)
                    this.Config.SAFTFileName = filename;

                Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.OPEN_SAFT_FILE, filename);
            }
        }

        internal void OpenPrivateKeyFile(string filename)
        {
            if (File.Exists(filename) && SAFT.SaftAnalyser.Instance.PrivateKeyFileName != filename)
            {
                SAFT.SaftAnalyser.Instance.PrivateKeyFileName = filename;

                if (this.Config.RememberLastOpenFiles && File.Exists(filename))
                    this.Config.PrivateKeyFileName = filename;

                Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.OPEN_PRIVATE_KEY_FILE, filename);
            }
        }

        internal void OpenPublicKeyFile(string filename)
        {
            if (File.Exists(filename) && SAFT.SaftAnalyser.Instance.PublicKeyFileName != filename)
            {
                SAFT.SaftAnalyser.Instance.PublicKeyFileName = filename;

                if (this.Config.RememberLastOpenFiles && File.Exists(filename))
                    this.Config.PublicKeyFileName = filename;

                Mediator.Instance.NotifyColleaguesAsync<string>(MessageType.OPEN_PUBLIC_KEY_FILE, filename);
            }
        }

        internal void OpenStockFile(string filename)
        {
            //on file open request all document parts to reset there values
            foreach (DocumentPartViewModel vm in this.DocumentParts)
            {
                vm.ResetStockFile();
            }

            if (File.Exists(filename))
            {
                SAFT.StockAnalyser.Instance.StockFileName = filename;
                SAFT.StockAnalyser.Instance.LoadFileAsync();
                
                if (this.Config.RememberLastOpenFiles)
                    this.Config.StockFileName = filename;
            }
        }

        string UpdateStatusMessage()
        {
            string mensagem = "Sem erros";

            if (SAFT.SaftAnalyser.Instance.MensagensErro.Count == 1)
                mensagem = "1 erro";
            else if (SAFT.SaftAnalyser.Instance.MensagensErro.Count > 1)
                mensagem = string.Format("{0} erros.", SAFT.SaftAnalyser.Instance.MensagensErro.Count);
            return mensagem;
        }

        public void ShowInvoiceDetails(SourceDocumentsSalesInvoicesInvoice invoice)
        {
            if (DocumentParts.OfType<InvoiceViewModel>().Count() == 0)
            {
                this.InvoiceDetails = new InvoiceViewModel(invoice);
                this.DocumentParts.Add(this.InvoiceDetails);
            }
            else
                this.InvoiceDetails.CurrentInvoice = invoice;

            this.InvoiceDetails.IsActive = true;
            this.InvoiceDetails.IsSelected = true;
            this.InvoiceDetails.IsVisible = true;
        }

        internal void ShowCustomer(string pk)
        {
            ShowDocumentPart(DocumentPart.Customers);
            this.Customers.FocusCustomer(pk);
        }

        public void ShowDocumentPart(DocumentPart part)
        {
            DocumentPartViewModel view = null;
            bool insert = false;
            switch (part)
            {
                case DocumentPart.Invoices:
                    view = this.Invoices;
                    insert = DocumentParts.OfType<InvoiceViewModel>().Count() == 0;
                    break;
                case DocumentPart.InvoicesSummary:
                    view = this.InvoicesSummary;
                    insert = DocumentParts.OfType<InvoicesSummaryViewModel>().Count() == 0;
                    break;
                case DocumentPart.MovementOfGoods:
                    view = this.MovementOfGoods;
                    insert = DocumentParts.OfType<MovementOfGoodsViewModel>().Count() == 0;
                    break;
                case DocumentPart.Payments:
                    view = this.Payments;
                    insert = DocumentParts.OfType<PaymentsViewModel>().Count() == 0;
                    break;
                case DocumentPart.WorkingDocuments:
                    view = this.WorkingDocuments;
                    insert = DocumentParts.OfType<WorkingDocumentsViewModel>().Count() == 0;
                    break;
                case DocumentPart.GeneralLedgerEntries:
                    view = this.GeneralLedgerEntries;
                    insert = DocumentParts.OfType<GeneralLedgerEntriesViewModel>().Count() == 0;
                    break;
                case DocumentPart.GeneralLedger:
                    view = this.GeneralLedger;
                    insert = DocumentParts.OfType<GeneralLedgerViewModel>().Count() == 0;
                    break;
                case DocumentPart.Customers:
                    view = this.Customers;
                    insert = DocumentParts.OfType<CustomersViewModel>().Count() == 0;
                    break;
                case DocumentPart.Supplier:
                    view = this.Supplier;
                    insert = DocumentParts.OfType<SupplierViewModel>().Count() == 0;
                    break;
                case DocumentPart.Products:
                    view = this.Products;
                    insert = DocumentParts.OfType<ProdutsViewModel>().Count() == 0;
                    break;
                case DocumentPart.Tax:
                    view = this.Tax;
                    insert = DocumentParts.OfType<TaxViewModel>().Count() == 0;
                    break;
                case DocumentPart.StockHeader:
                    view = this.StockHeader;
                    insert = DocumentParts.OfType<StockHeaderViewModel>().Count() == 0;
                    break;
                case DocumentPart.StockProducts:
                    view = this.StockProducts;
                    insert = DocumentParts.OfType<StocksProductsViewModel>().Count() == 0;
                    break;
                default:
                    break;
            }

            DocumentParts.Remove(view);
            DocumentParts.Add(view);

            view.IsActive = true;
            view.IsSelected = true;
            view.IsVisible = true;
        }

        #region Application_Exit_Command
        private void AppExit_CommandExecuted()
        {
            try
            {
                if (this.Closing_CanExecute() == true)
                {
                    this.mShutDownInProgress_Cancel = false;
                    this.OnRequestClose();
                }
            }
            catch (Exception exp)
            {
                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }
        }
        #endregion Application_Exit_Command

        #region Application_About_Command
        private void AppAbout_CommandExecuted()
        {
            try
            {
                ServiceResolver.Instance.UIVisualizerService.ShowDialog("AboutView", new AboutViewModel());
            }
            catch (Exception exp)
            {
                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }
        }
        #endregion Application_About_Command

        #region Application_Preferences_Command
        private void AppPreferences_CommandExecuted()
        {
            try
            {
                //bool? result = ServiceResolver.Instance.UIVisualizerService.ShowDialog("CodePropertiesView", vm);
                //if (!result.GetValueOrDefault())
                //{

                //}
            }
            catch (Exception exp)
            {
                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }
        }
        #endregion Application_About_Command

        #region RequestClose [event]

        /// <summary>
        /// Raised when this workspace should be removed from the UI.
        /// </summary>
        public event EventHandler RequestClose;

        /// <summary>
        /// Method to be executed when user (or program) tries to close the application
        /// </summary>
        public void OnRequestClose()
        {
            try
            {
                if (this.mShutDownInProgress == false)
                {
                    if (this.DialogCloseResult == null)
                        this.DialogCloseResult = true;      // Execute Close event via attached property

                    if (this.mShutDownInProgress_Cancel == true)
                    {
                        this.mShutDownInProgress = false;
                        this.mShutDownInProgress_Cancel = false;
                        this.DialogCloseResult = null;
                    }
                    else
                    {
                        this.mShutDownInProgress = true;

                        CommandManager.InvalidateRequerySuggested();

                        EventHandler handler = this.RequestClose;

                        if (handler != null)
                            handler(this, EventArgs.Empty);
                    }
                }
            }
            catch (Exception exp)
            {
                this.mShutDownInProgress = false;

                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }
        }
        #endregion // RequestClose [event]

        /// <summary>
        /// This can be used to close the attached view via ViewModel
        /// 
        /// Source: http://stackoverflow.com/questions/501886/wpf-mvvm-newbie-how-should-the-viewmodel-close-the-form
        /// </summary>
        public bool? DialogCloseResult
        {
            get { return this.mDialogCloseResult; }

            private set
            {
                if (this.mDialogCloseResult != value)
                {
                    this.mDialogCloseResult = value;
                    NotifyPropertyChanged(Cinch.ObservableHelper.CreateArgs<Workspace>(x => x.DialogCloseResult));
                }
            }
        }

        /// <summary>
        /// Check if pre-requisites for closing application are available.
        /// Save session data on closing and cancel closing process if necessary.
        /// </summary>
        /// <returns>true if application is OK to proceed closing with closed, otherwise false.</returns>
        internal bool Exit_CheckConditions(object sender)
        {
            if (this.mShutDownInProgress == true)
                return true;

            try
            {
                try
                {
                    App.CreateAppDataFolder();
                    this.SerializeLayout(sender);            // Store the current layout for later retrieval
                }
                catch { }
            }
            catch (Exception exp)
            {
                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }

            return true;
        }

        internal void SerializeLayout(object sender)
        {
            XmlLayoutSerializer xmlLayout = null;
            MainWindowView mainWin = null;

            if (sender != null)
                mainWin = sender as MainWindowView;

            // save the dockManager Layout
            if (mainWin != null)
            {
                xmlLayout = new XmlLayoutSerializer(mainWin.dockManager);

                xmlLayout.Serialize(System.IO.Path.Combine(App.DirAppData, LayoutFileName));
            }
        }

        /// <summary>
        /// Set the active document to the file in <seealso cref="fileNamePath"/>
        /// if this is currently open.
        /// </summary>
        /// <param name="fileNamePath"></param>
        internal bool SetActiveDocument(DocumentPartViewModel documentPart)
        {
            try
            {
                if (this.DocumentParts.Count >= 0)
                {
                    DocumentPartViewModel fi = this.DocumentParts.SingleOrDefault(f => f.Name == documentPart.Name);

                    if (fi != null)
                    {
                        this.ActiveDocument = fi;
                        return true;
                    }
                }
            }
            catch (Exception exp)
            {
                //logger.ErrorException(exp.Message, exp);
                ServiceResolver.Instance.MessageBoxService.ShowError(exp.Message, "Unhandled Error");
            }

            return false;
        }
        #endregion methods
    }
}
